package com.laizhenghua.hystrix.controller;

import cn.hutool.core.util.IdUtil;
import com.laizhenghua.commons.utils.R;
import com.laizhenghua.hystrix.service.PaymentService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @description:
 * @date: 2022/2/12 17:16
 */
@Slf4j
@RestController
@RequestMapping(path = "/payment")
public class PaymentController {
    @Autowired
    private PaymentService paymentService;
    /**
     * 正常方法（不会超时，也不会出现异常）
     * @return R
     */
    @RequestMapping(path = "/testOk", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
    public R testOk() {
        Map<String, String> data = new HashMap<>();
        data.put("threadName", Thread.currentThread().getName());
        data.put("methodName", "testOk");
        return R.ok().put("data", data);
    }

    /**
     * 异常方法（出现超时或异常）
     * @return R
     */
    @RequestMapping(path = "/testError", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
    public R testError() {
        return R.ok().put("data", paymentService.testError());
    }

    /**
     * 服务熔断配置示例
     * @param id
     * @return R
     */
    @HystrixCommand(fallbackMethod = "paymentCircuitBreakerFallback", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), // 是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60") // 失败率阈值 %60
    })
    @RequestMapping(path = "/circuitBreaker/{id}", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public R paymentCircuitBreaker(@PathVariable(value = "id") Integer id) {
        if (id < 0) {
            throw new RuntimeException("id 不能为负数");
        }
        // https://www.hutool.cn/
        String uuid = IdUtil.simpleUUID(); // String uuid = UUID.randomUUID().toString().replace("-", "");
        return R.ok().put("uuid", uuid);
    }
    public R paymentCircuitBreakerFallback(Integer id) {
        return R.error(1000, id + " 不能为负数！");
    }
}
